import * as fs from 'fs';
import * as vscode from 'vscode';
import { binarySearch, binarySearchIndex, BinarySearchMask } from './BinarySearch';

let HGAPPID: number;
async function getHGAPPID(): Promise<number | undefined> {
	// if (!!HGAPPID) {
	// 	return HGAPPID;
	// }
	const workspaceFolders = vscode.workspace.workspaceFolders;
	if (!workspaceFolders) {
		vscode.window.showInformationMessage('workspace undefined');
	} else {
		//获取的内容
		const indexURI = vscode.Uri.joinPath(workspaceFolders[0].uri, "index.html");
		const document = await vscode.workspace.openTextDocument(indexURI);
		const matchReg = new RegExp(/var HGAPPID = ([0-9]*);/);
		let res = document.getText().match(matchReg);
		if (!res) {
			return;
		}
		HGAPPID = +res[1];
	}
	return HGAPPID;
}

async function getComstrDocument(): Promise<vscode.TextDocument | undefined> {
	const workspaceFolders = vscode.workspace.workspaceFolders;
	if (!workspaceFolders) {
		vscode.window.showInformationMessage('workspace undefined');
	} else {
		//获取comstr的内容
		const comstrUri = vscode.Uri.joinPath(workspaceFolders[0].uri, await getOutputFile());
		return await vscode.workspace.openTextDocument(comstrUri);
	}
}

async function getLineAsync(id: string, showMsg: boolean = true) {
	const document = await getComstrDocument();
	if (!document) {
		return;
	}
	//正则匹配指定行
	const matchReg = new RegExp(/\[([0-9]+), ?"(.+)"\]/);
	let line;
	let comstrValue;
	for (let index = 0; index < document.lineCount; index++) {
		line = document.lineAt(index);
		let res = line.text.match(matchReg);
		if (res && res[1] == id) {
			comstrValue = res[2];
			// vscode.window.showInformationMessage(res[2]);
			break;
		}
	}
	if (!comstrValue || !line) {
		showMsg && vscode.window.showInformationMessage("no such comstr");
		return;
	}
	return { line: line, text: comstrValue, document: document };
}

export async function readComstrAsync() {
	const document = await getComstrDocument();
	if (!document) {
		return;
	}
	//获取激活编辑器选中的内容
	const activeEditor = vscode.window.activeTextEditor;
	const cursorPosition = activeEditor?.selection.start;
	const wordRange = cursorPosition && activeEditor?.document.getWordRangeAtPosition(cursorPosition);
	const highlight = activeEditor?.document.getText(wordRange);
	let value;
	//激活的编辑器选中了数字
	if (!!highlight && !isNaN(+highlight)) {
		value = highlight;
	}
	const input = await vscode.window.showInputBox({
		prompt: "请输入comstrID",
		value: value
	});

	if (!input) {
		return;
	}
	//正则匹配指定行
	const res = await getLineAsync(input);
	if (!res) {
		return;
	}
	let line = res.line;
	let comstrValue = res.text;

	//输出对应的字符串
	const output = await vscode.window.showInputBox({
		value: comstrValue,
		prompt: "请输入修改内容",
	});
	//没有进行更改时返回
	if (output == comstrValue) {
		return;
	}
	//更改了打开comstr对对应行进行更改
	const range = line.range;
	const comstrEditor = await vscode.window.showTextDocument(document, { preserveFocus: false, preview: false, selection: range });
	const replaceReg = new RegExp(/(\[[0-9]+, ?")(.+)("\])/);
	const newText = line.text.replace(replaceReg, "$1" + output + "$3");
	comstrEditor.edit(edit => {
		edit.replace(range, newText);
	})
}

type ComstrItem = [number, string];

async function getExistingItems() {
	const workspaceFolders = vscode.workspace.workspaceFolders;
	if (!workspaceFolders) {
		vscode.window.showInformationMessage('workspace undefined');
		return;
	}
	const existingItems: Array<ComstrItem> = [];
	const sourceFiles = vscode.workspace.getConfiguration().get<Array<string>>("comstr.sourceFiles") || [];
	for (const sourceFile of sourceFiles) {
		const sourceUri = vscode.Uri.joinPath(workspaceFolders[0].uri, sourceFile);
		if (!fs.existsSync(sourceUri.fsPath)) {
			vscode.window.showInformationMessage("comstr文件不存在");
			return;
		}
		const comstrFileData = fs.readFileSync(sourceUri.fsPath, 'utf8');
		//解析成对象找到ID,防止Comstr的ID乱序
		let jsonObj: { guistr: Array<ComstrItem> };
		try {
			jsonObj = JSON.parse(comstrFileData);
		} catch (error) {
			vscode.window.showInformationMessage("jsonObj解析失败");
			return;
		}
		existingItems.push(...jsonObj.guistr);
	}
	return existingItems;
}

async function getOutputFile() {
	return vscode.workspace.getConfiguration().get<string>("comstr.outputFile") || "resource/assets/cfgjson/comstr.json";
}

export async function addComstrAsync() {
	const workspaceFolders = vscode.workspace.workspaceFolders;
	if (!workspaceFolders) {
		vscode.window.showInformationMessage('workspace undefined');
		return;
	}
	const comstrItems = await getExistingItems();
	if (!comstrItems) {
		return;
	}
	const comstrArr = comstrItems.map(strItem => strItem[0]).sort((a, b) => a - b);
	const input = await vscode.window.showInputBox({
		prompt: "请输入内容",
	});

	if (!input) {
		return;
	}

	const begID: number | undefined = vscode.workspace.getConfiguration().get("comstr.useridBeg");
	const appID: number | undefined = await getHGAPPID();
	if (!begID || !appID) {
		vscode.window.showInformationMessage("配置不存在");
		return;
	}
	let insertID = +("" + appID + begID);
	for (let index = 0; index < comstrArr.length; index++) {
		const id = comstrArr[index];
		if (id === insertID) {
			insertID++;
		}
	}

	const outputFile = vscode.workspace.getConfiguration().get<string>("comstr.outputFile");
	if (!outputFile) {
		vscode.window.showInformationMessage("outputFile配置不存在");
		return;
	}
	const outputFileUri = vscode.Uri.joinPath(workspaceFolders[0].uri, outputFile);
	const comstrFileData = fs.readFileSync(outputFileUri.fsPath, 'utf8');
	
	//正则匹配指定行
	let hasInsertFlag = false;
	let data: string[] = comstrFileData.split(/\r\n|\n|\r/gm).filter(v => v.trim());
	const matchReg = new RegExp(/\[([0-9]+), ?"(.+)"\]/);
	const index = binarySearchIndex(data, (line) => {
		const res = line.match(matchReg);
		const id = +(res && res[1] || 0);
		return id - insertID;
	}, BinarySearchMask.nearbyGreater);
	if (index < 0) {
		vscode.window.showInformationMessage(`插入id=${insertID}失败！`);
		return;
	}
	data.splice(index, 0, `\t\t[${insertID}, "${input}"],`);
	fs.writeFileSync(outputFileUri.fsPath, data.join('\r\n'));

	//在激活编辑器的光标处加入数字
	const activeEditor = vscode.window.activeTextEditor;
	const cursorPosition = activeEditor?.selection.start;
	if (cursorPosition) {
		activeEditor.edit(edit => {
			edit.insert(cursorPosition, "" + insertID + `/*${input}*/`);
		});
	}
}

export async function addComstrCommentAsync() {
	const document = await getComstrDocument();
	if (!document) {
		return;
	}
	//获取激活编辑器选中的内容
	const activeEditor = vscode.window.activeTextEditor;
	if (!activeEditor) {
		return;
	}
	const insertList: { pos: vscode.Position, value: string }[] = [];
	for (let index = 0; index < activeEditor.selections.length; index++) {
		const cursorPosition = activeEditor.selections[index].start;
		const wordRange = activeEditor.document.getWordRangeAtPosition(cursorPosition);
		if (!wordRange) {
			continue;
		}
		const highlight = activeEditor?.document.getText(wordRange);
		let value;
		//激活的编辑器选中了数字
		if (!!highlight && !isNaN(+highlight)) {
			value = highlight;
		} else {
			vscode.window.showInformationMessage("没有选中数字");
			continue;
		}

		const res = await getLineAsync(value);
		if (!res) {
			vscode.window.showInformationMessage("没有数字" + value + "对应的comstr");
			continue;
		}
		insertList.push({ pos: wordRange.end, value: `/*${res.text}*/` });
	}

	//在激活编辑器的光标处加入数字
	activeEditor?.edit(edit => {
		for (let i = 0; i < insertList.length; i++) {
			edit.insert(insertList[i].pos, insertList[i].value);
		}
	})
}

export async function showComstr() {
	vscode.languages.registerHoverProvider(['typescript', 'javascript'], {
		async provideHover(document, position) {
			if (!document.getWordRangeAtPosition(position)) {
				return
			}
			let word = document.getText(document.getWordRangeAtPosition(position))
			let selectText = vscode.window.activeTextEditor?.document.getText(vscode.window.activeTextEditor.selection)
			if (selectText && word.indexOf(selectText) > -1) {
				word = selectText
			}
			if (isNaN(+word) || word.length < 7 || word.length > 11) {
				return;
			}
			const res = await getLineAsync(word, false);
			let hoverText;
			if (res) {
				hoverText = res.text.length ? res.text : "...";
			} else {
				return;
			}
			return new vscode.Hover(hoverText)
		}
	})

	vscode.languages.registerDefinitionProvider(['typescript', 'javascript'], {
		async provideDefinition(document, position, token) {
			if (!document.getWordRangeAtPosition(position)) {
				return
			}
			let word = document.getText(document.getWordRangeAtPosition(position))
			let selectText = vscode.window.activeTextEditor?.document.getText(vscode.window.activeTextEditor.selection)
			if (selectText && word.indexOf(selectText) > -1) {
				word = selectText
			}
			if (isNaN(+word) || word.length < 7 || word.length > 11) {
				return;
			}
			const res = await getLineAsync(word, false);
			let hoverText;
			if (res) {
				hoverText = res.text.length ? res.text : "...";
			} else {
				return;
			}
			return new vscode.Location(res.document.uri, res.line.range)
		}
	})
}